package chapter02.singleton.job;

import java.util.concurrent.locks.ReentrantLock;

// 模拟数据库连接类
class MockDBConnection {
    private boolean isConnected = false;

    public MockDBConnection() {
        // 模拟数据库连接初始化过程
        try {
            Thread.sleep(1000);
            isConnected = true;
            System.out.println("数据库连接已建立");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void executeQuery(String sql) {
        if (isConnected) {
            System.out.println("执行SQL查询: " + sql);
        } else {
            throw new IllegalStateException("数据库连接未初始化");
        }
    }
}

// 线程安全的单例类
public class ThreadSafeSingleton {
    // 使用volatile关键字保证多线程环境下的可见性
    private static volatile ThreadSafeSingleton instance;
    // 数据库连接对象
    private MockDBConnection connection;
    // 重入锁用于同步初始化操作
    private static final ReentrantLock lock = new ReentrantLock();

    // 私有构造函数防止外部实例化
    private ThreadSafeSingleton() {}

    // 获取单例实例的方法
    public static ThreadSafeSingleton getInstance() {
        // 第一次检查，避免不必要的同步
        if (instance == null) {
            // 同步代码块确保只有一个线程进入
            lock.lock();
            try {
                // 第二次检查，防止多个线程同时通过第一次检查
                if (instance == null) {
                    instance = new ThreadSafeSingleton();
                }
            } finally {
                lock.unlock();
            }
        }
        return instance;
    }

    // 获取数据库连接的方法
    public MockDBConnection getConnection() {
        // 双重检查锁定确保连接只初始化一次
        if (connection == null) {
            synchronized (this) {
                if (connection == null) {
                    connection = new MockDBConnection();
                }
            }
        }
        return connection;
    }

    // 测试方法
    public static void main(String[] args) {
        // 模拟多线程环境下的调用
        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                ThreadSafeSingleton singleton = ThreadSafeSingleton.getInstance();
                MockDBConnection conn = singleton.getConnection();
                conn.executeQuery("SELECT * FROM users");
            }).start();
        }
    }
}